﻿using Common.Utils;
using Microsoft.Extensions.DependencyInjection;
using Serilog.Core;
using Serilog.Events;

namespace Infrastructure.Extensions;

#nullable disable

public class CustomDatabaseLogSink : ILogEventSink
{
    private readonly IServiceProvider _serviceProvider;
    private readonly ICurrentUserService _userService;
    private readonly IDateTime _dateTime;
    public CustomDatabaseLogSink(
        IServiceProvider serviceProvider,
        ICurrentUserService userService,
        IDateTime dateTime)
    {
        _serviceProvider = serviceProvider;
        _userService = userService;
        _dateTime = dateTime;
    }

    public async void Emit(LogEvent logEvent)
    {
        if (logEvent == null) { return; }
        if (logEvent.Level == LogEventLevel.Debug) { return; }

        try
        {
            await SaveLoggerAsync(logEvent);
        }
        catch (Exception )
        {
        }
    }

    public async Task SaveLoggerAsync(LogEvent logEvent)
    {
        var properties = new Dictionary<string, object>();
        var aa = logEvent.Properties.ToReadableJson();
        foreach (var property in logEvent.Properties)
        {
            var value = property.Value.ToString();
            if (value is not null && value.StartsWith(@"""{"))
            {
                properties[property.Key] = value;
                continue;
            }
            if (value is not null && value.StartsWith(@""""))
            {
                value = value.Replace(@"""", "");
                properties[property.Key] = value;
                continue;
            }
            properties[property.Key] = value;
        }

        Domain.Entities.Loggers.Logger logger = new Domain.Entities.Loggers.Logger()
        {
            UserId = _userService.CurrentUserId == 0 ? null : _userService.CurrentUserId,
            TenantId = _userService.TenantId,
            Level = logEvent.Level.ToString(),
            Message = logEvent.RenderMessage(),
            MessageTemplate = logEvent.MessageTemplate.ToString(),
            Exception = logEvent.Exception?.ToString(),
            Timestamp = _dateTime.Now,
            TimestampLong = _dateTime.Now.ToUnixTimestampMilliseconds(),
            Properties = properties.ToJson(),
        };

        using (var scope = _serviceProvider.CreateScope())
        {
            var _context = scope.ServiceProvider.GetRequiredService<IApplicationDbContext>();

            await _context.Loggers.AddAsync(logger);
            await _context.SaveChangesAsync().ConfigureAwait(false);
        }
    }
}
